<?php

namespace app\api\service;

use app\model\Dashboard;
use app\model\DeviceSync;
use app\model\GrainSituation;
use app\model\Stock;
use app\traits\ServiceTrait;
use app\traits\UserTrait;
use think\Collection;
use think\db\exception\DbException;
use think\helper\Arr;
use think\Model;

class ReportService
{
    use UserTrait;
    use ServiceTrait;

    /**
     * 同步硬件信息表
     * @param $data
     * @return void
     * @throws \Exception
     */
    public function deviceSync($data): void
    {
        $model = new DeviceSync();
        DeviceSync::destroy(function ($query) {
            $query->where('id', '>', 0);
        }, true);
        $model->saveAll($data);
    }

    /**
     * 首页数据上报
     * @param $data
     * @param $pushTime
     * @return Collection
     * @throws \Exception
     */
    public function addDashboard($data, $pushTime): \think\Collection
    {
        $model = new Dashboard();
        $insertData = [];
        foreach ($data as $item) {
            $insertData[] = [
                'stock_id' => Arr::get($item, 'stock_id'),
                'temperature_inside_avg' => Arr::get($item, 'temperature_inside_avg'),
                'temperature_outside_avg' => Arr::get($item, 'temperature_outside_avg'),
                'humidity_avg' => Arr::get($item, 'humidity_avg'),
                'sensor' => Arr::get($item, 'sensor'),
                'electric' => Arr::get($item, 'electric'),
                'push_time' => $pushTime,
            ];
        }
        return $model->saveAll($insertData);
    }

    /**
     * 粮情数据上报
     * @param $data
     * @return bool
     */
    public function addGrainSituation($data): bool
    {
        $model = new GrainSituation();
        $insert = [
            'stock_id' => Arr::get($data, 'stock_id'),
            'push_time' => Arr::get($data, 'push_time'),
            'grain_json' => Arr::get($data, 'grain_json'),
        ];
        return $model->save($insert);
    }


    /**
     * 最新的首页面板数据
     * @param $stockId
     * @param $limit
     * @return array|\ArrayAccess|mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function dashboard($stockId, $limit = 7): mixed
    {
        $data = Dashboard::where(['stock_id' => $stockId])->where('id', 'in', function ($query) use ($limit, $stockId) {
            $query->table('dashboard')->where(['stock_id' => $stockId])->field('max(id)')->group("DATE_FORMAT(push_time, '%Y-%m-%d')");
        })->field(['temperature_inside_avg', 'temperature_outside_avg', 'humidity_avg', 'electric', 'sensor'])
            ->limit($limit)
            ->select()
            ->order('push_time', 'asc')
            ->toArray();
        $latest = Arr::get($data, '0');
        $alterSensor = $electric = [];
        //近几天的电量
        $electrics = array_column($data, 'electric');
        foreach ($electrics as $eItem) {
            if (is_array($eItem)) {
                foreach (Arr::get($eItem, '0') as $item) {//由数组调整为对象,需要兼容之前结构
                    $electric['x_data'][] = date('Y-m-d', strtotime($item->date));
                    $electric['y_data'][] = $item->quantity;
                }
            } else {
                $electric['x_data'][] = date('Y-m-d', strtotime($eItem->date));
                $electric['y_data'][] = $eItem->quantity;
            }
        }
        //当前仅报警的数据
        foreach (Arr::get($latest, 'sensor') ?: [] as $item) {
            if ($item->temperature?->alert == 1) {
                $alterSensor[] = [
                    'type' => 1,
                    'position' => $item->temperature?->position ?? '',
                    'value' => $item->temperature?->value ?? 0,
                ];
            }
            if ($item->humidity?->alert == 1) {
                $alterSensor[] = [
                    'type' => 2,
                    'position' => $item->humidity?->position ?? '',
                    'value' => $item->humidity?->value ?? 0,
                ];
            }
        }
        unset($latest['sensor']);
        $latest['alert_list'] = $alterSensor;
        $latest['electric'] = $electric;
        return $latest;
    }

    /**
     * 获取粮情信息
     * @param $params
     * @return GrainSituation|array|mixed|Model
     */
    public function grainSituation($params)
    {
        $stockId = Arr::get($params, 'stock_id');
        $id = Arr::get($params, 'id');
        if (!$stockId && !$id) {
            return [false, '缺少必要参数stock_id'];
        }

        // 传id时,按id查找
        if ($id = Arr::get($params, 'id')) {
            return [true, GrainSituation::where(['id' => $id])->findOrEmpty()];
        }

        return [true, GrainSituation::where(['stock_id' => $stockId])->order('id', 'desc')->findOrEmpty()];
    }

    /**
     * 获取粮情信息列表
     * @param $stockSn
     * @return GrainSituation|array|mixed|\think\Model
     * @throws DbException
     */
    public function grainSituationHistory($params): mixed
    {
        $stockId = Arr::get($params, 'stock_id');
        $query = GrainSituation::where(['stock_id' => $stockId])->order('id', 'desc');
        if ($pushTime = Arr::get($params, 'push_time')) {
            $query->where('push_time', 'like', "$pushTime%");
        }
        return $query->field(['id', 'stock_id', 'push_time'])
            ->paginate([
                'list_rows' => Arr::get($params, $this->listRowsName('system'), 15),
                'var_page' => 'page',
            ]);
    }

    public function statistics()
    {
        $data = [];
        $alert = [];
        Dashboard::where('id', 'in', function ($query) {
            $query->table('dashboard')->field('max(id)')->group('stock_id');
        })->with('stock')
            ->select()->order('id', 'desc')->each(function ($item) use (&$data, &$alert) {
            foreach (Arr::get($item, 'sensor') ?? [] as $sensor) {
                if ($sensor->temperature?->alert == 1) {
                    $alert[] = [
                        'stock_id' => $item['stock_id'],
                        'position' => $sensor->position ?? '',
                        'temperature' => $sensor->temperature?->value ?? 0,
                        'stock_name' => $item->stock?->name,
                        'stock_no' => $item->stock?->serial_no,
                        'push_time' => $item->push_time,
                    ];
                }
                $data[] = [
                    'stock_id' => $item['stock_id'],
                    'position' => $sensor->position ?? '',
                    'temperature' => $sensor->temperature?->value ?? 0,
                    'humidity' => $sensor->humidity?->value ?? 0,
                    'stock_name' => $item->stock?->name,
                    'stock_no' => $item->stock?->serial_no,
                ];
            }
        });
        return ['all' => $data, 'alert' => $alert, 'fans' => [
            'x_data' => ['10-23', '10-24'],
            'y_data' => [1,3]
        ]];
    }

}